iT邦幫忙

2023 iThome 鐵人賽

DAY 21
0
Mobile Development

SwiftUI 的大大小小系列 第 21

Day 21 - 在 SwiftUI 中使用 navigationDestination 封裝開啟畫面

  • 分享至 

  • xImage
  •  

hero

在前面這兩天有聊到 NavigationStack 和 NavigationLink 。NavigationStack 可以創建出 UINavigationController 那樣子的畫面,而 NavigationLink 可以達成和 push view controller 一樣的效果。

結果圖

2101

NavigationLink 的潛在問題

NavigationLink("下一頁") {
    SomeView()
}

NavigationLink 能夠像這樣子,透過 closure 可以回傳想要顯示的 UI 元件

但是當有畫面中有多個和不同種類的 NavigationLink 的時候,就會充斥著這一類型的 closures 。

這時候就可以透過 navigationDestination 來統整。

起始畫面

struct ContentView: View {
    private let flavors = ["綠豆", "紅豆", "芋粿", "愛玉"]
    var body: some View {
        NavigationStack {
            ForEach(flavors, id: \.self) { flavor in
                NavigationLink(flavor) {
                    Text(flavor)
                        .navigationTitle(flavor)
                }
                .padding()
            }
        }
    }
}

換成 navigationDestination

  1. 換上可以傳入 value 的 NavigationLink
  2. 加上 navigationDestination ,將要顯示的畫面移到這裡

這時候 navigationDestination 需要加入和第二個參數 value 吻合的型別,在這邊則是 String 。

而到 navigationDestination 的 closure 裡就能夠接收到傳入 value 的值。

struct ContentView: View {
    private let flavors = ["綠豆", "紅豆", "芋粿", "愛玉"]
    var body: some View {
        NavigationStack {
            ForEach(flavors, id: \.self) { flavor in
                NavigationLink(flavor, value: flavor).padding()
            }
            .navigationDestination(for: String.self) { flavor in
                Text(flavor)
                    .navigationTitle(flavor)
            }
        }
    }
}

定義成特定 Data Model

由於 String 這個型別太廣泛,因此我們可以像這樣定義一個 Flavor 、在 navigationDestination 的地方就能夠特定到 Flavor 這個型別了:

struct Flavor: Identifiable, Hashable {
    let id = UUID().uuidString
    let name: String
}

struct ContentView: View {
    private let flavors = ["綠豆", "紅豆", "芋粿", "愛玉"].map(Flavor.init)
    var body: some View {
        NavigationStack {
            ForEach(flavors) { flavor in
                NavigationLink(flavor.name, value: flavor).padding()
            }
            .navigationDestination(for: Flavor.self) { flavor in
                Text(flavor.name)
                    .navigationTitle(flavor.name)
            }
        }
    }
}

結語

以上,那今天的 SwiftUI 的大大小小就到這邊,明天見!

環境

  • Xcode 15

本篇使用到的 UI 元件和 modifiers 基本上沒有受到版本更新影響。若要在 Xcode 14 等環境下使用也是沒問題的。


上一篇
Day 20 - SwiftUI 中的 NavigationStack 使用 NavigationLink 與 dismiss
下一篇
Day 22 - SwiftUI 的 NavigationStack 與 path - 1
系列文
SwiftUI 的大大小小30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言